# -*- coding:utf-8 -*-
import Tkinter as tk
import tkFileDialog
from transcode import *
import io
import json
import threading
import time
from transform import *
import tkMessageBox
import requests
import traceback
#区划后缀列表
qhendstrs = [u'村村委会',u'村委会',u'村民委员会',u'社区',u'居委会']
#户籍前缀列表
hjfrontstrs = [u'办事处',u'镇',u'乡']
#户籍后缀列表
hjendstrs = [u'村',u'社区',u'居委会']
jpfields = ['NAME', 'AREA_CODE']
rpfields = ['codeName','code']
shpfields = jpfields
username = ''
userareacode = ''
gb_apitype = 'bd'#接口类型——高德:gd,百度:bd
#提取户籍村居简称
def gethjsimple(address):
    #提取简称
    okfront = u''
    for front in hjfrontstrs:
        frontpos = address.find(front)
        if frontpos>0:
            okfront = front
            break
    for end in hjendstrs:
        endpos  = address.find(end)
        if endpos>0:
            break
    print address,frontpos,endpos,okfront,len(okfront),address[frontpos+len(okfront):endpos]
    if  frontpos> 0 and endpos>0:
        return address[frontpos+len(okfront):endpos]
    return ''

#生成区划简称查询字典
def getareadict(areacodes):
    areacodedict = {}
    for area in areacodes:
        if area[1][0:len(userareacode)] != userareacode and userareacode!='*':
            outinfo.insert('end','区划中含有非授权区域,退出处理进程')
            return {'error':-1}
            # os._exit(0)
            # main_box.quit()
        #提取简称
        for end in qhendstrs:
            endpos = area[0].find(end)
            if  endpos>0:
                simplename = area[0][0:endpos]
                areacodedict[simplename] = area
                break
    return areacodedict

def execProcess(apitype='bd'):
    datasource = path_shp.get()   #ur'村边界_bd.shp'
    #输入输出shp
    datasource = datasource[0:datasource.find('.shp')]
    outFeature = datasource +'_'+apitype
    ###构造转换，待加入异常处理
    # if bjtype.get()=='jp':
    #     shpfields = jpfields
    # else:
    #     shpfields = rpfields
    precoder = Transcoder(datasource)
    shpkeys = precoder.getfields()
    print shpkeys
    if 'NAME' in shpkeys:
        shpfields = jpfields
    elif 'code' in shpkeys:
        shpfields = rpfields
    else:
        outinfo.insert('end','边界字段不符\n')
        return
    print shpfields
    precoder.setFields(shpfields)
    #读取边界文件区划库
    try:
        areacodes = precoder.codes()
    except:
        outinfo.insert('end','边界文件格式不符\n')
        return
    #生成区划简称字典
    areacodedict = getareadict(areacodes)
    if 'error' in areacodedict:
        return

    ###生成区划代码文件，待加入异常处理
    with open(u'区划代码.csv','w') as fqh:
        for d in areacodedict:
            fqh.write('%s,%s,%s\n'%(d,areacodedict[d][0],areacodedict[d][1]))
    #生成匹配用coder
    #转百度坐标
    outinfo.insert('end','转换至百度坐标系...\n')
    TransformFeature(datasource,outFeature,gb_apitype)
    outinfo.insert('end','坐标转换完成,开始地址匹配...\n')
    processcoder = Transcoder(outFeature)
    processcoder.setFields(shpfields)
    #输出匹配结果csv表头
    ###待加入异常处理
    outputcsv = u'匹配结果'+time.strftime("%Y_%m_%d_%H_%M_%S", time.localtime()) +'.csv'
    with open(outputcsv,'w') as fout:
        resfields = '理解程度,是否精确查找,打点精度,地址类型,'
        if userjson['isdebug'] == '1':
            fout.write('地址,融合村居名,融合村居码,百度匹配村居名,百度匹配村居码,经度,纬度,'+resfields+'村居简称,简称匹配村居名,简称匹配村居码\n')
        else:
            fout.write('地址,匹配村居名,匹配村居码,经度,纬度,'+resfields+'\n')
        #已查询缓存
        reslist = {}
        with io.open(path_txt.get(), "r",encoding='utf-8') as f:
            for index,line in enumerate(f.readlines()):    
                if userjson['haspayed'] == '0' and index >=1000:
                    outinfo.insert('end','试用账号权限为1000条数据\n')
                    break
                try:
                    inAddress = line.strip().replace(u' ', u'')  #去掉头尾空字符中间空格
                    if  inAddress=='':
                        print u'空行'
                        continue
                    #先在缓存中查找
                    if inAddress in reslist:
                        result = reslist[inAddress]
                        print inAddress+u' 读缓存'
                    else:
                        #空间查询匹配
                        result = processcoder.trans(inAddress,gb_apitype)
                        result['addr'] = inAddress
                        reslist[inAddress] = result
                        #区划简称匹配
                        #提取户籍简称
                        if index==0:
                            inAddress = inAddress.replace(u'\ufeff','')
                        hjsimple = gethjsimple(inAddress)
                        result['hjsimple'] = hjsimple
                        if hjsimple in areacodedict and hjsimple != '':
                            result['qhname'] = areacodedict[hjsimple][0]
                            result['qhcode'] = areacodedict[hjsimple][1]
                        else:
                            result['qhname'] = ''
                            result['qhcode'] = ''
                    if userjson['isdebug'] == '1':
                        fout.write(u'%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s\n' % (inAddress,
                        result['qhname'] if result['qhname']!='' else result['coding'][shpfields[0]] if result['coding'] else '',
                        result['qhcode'] if result['qhcode']!='' else result['coding'][shpfields[1]] if result['coding'] else '',
                        result['coding'][shpfields[0]] if result['coding'] else '',
                        result['coding'][shpfields[1]] if result['coding'] else '',
                        result['location'].split(',')[0] if apitype=='gd' else result['location']['lng'],
                        result['location'].split(',')[1] if apitype=='gd' else result['location']['lat'],
                        result.get('comprehension',''),result.get('precise',''),result.get('confidence',''),result.get('level',''),
                        result['hjsimple'],result['qhname'],result['qhcode']))
                    else:
                        fout.write(u'%s,%s,%s,%s,%s,%s,%s,%s,%s\n' % (inAddress,
                        result['qhname'] if result['qhname']!='' else result['coding'][shpfields[0]] if result['coding'] else '',
                        result['qhcode'] if result['qhcode']!='' else result['coding'][shpfields[1]] if result['coding'] else '',
                        result['location'].split(',')[0] if apitype=='gd' else result['location']['lng'],
                        result['location'].split(',')[1] if apitype=='gd' else result['location']['lat'],
                        result.get('comprehension',''),result.get('precise',''),result.get('confidence',''),result.get('level','')))

                    outinfo.insert('end','%s:%s\n' %(index,inAddress))
                    outinfo.see('end')
                except Exception as e:
                    outinfo.insert('end',traceback.format_exc())
                    return
                    # outinfo.insert('end',repr(e)+'\n')
    outinfo.insert('end','地址匹配完成\n')
    os.startfile(outputcsv)

def selectPath(type,textui):
    #选择文件path_接收文件地址
    path_ = tkFileDialog.askopenfilename(filetypes=[(type,'*.'+type)])
    #通过replace函数替换绝对文件地址中的/来使文件可被程序读取 
    #注意：\\转义后为\，所以\\\\转义后为\\
    path_=path_.replace("/","\\\\")
    #path设置path_的值
    textui.set(path_)

def createMainForm():
    #生成UI
    global main_box
    main_box= tk.Tk()
    main_box.title('第七次人口普查地址匹配工具')
    main_box.withdraw()
    #变量path
    global path_shp
    path_shp = tk.StringVar()
    global path_txt
    path_txt = tk.StringVar()
    #说明
    info = tk.Text(main_box)
    info.insert('insert',
'''输入的地址列表为文本文件，每行一个地址，utf8编码
边界文件为shp格式，支持四经普边界和人普边界，程序能够自动识别
输出结果为同目录的'地址匹配.csv'文件
输出结果字段说明：
理解程度：
    描述地址理解程度。分值范围0-100，分值越大，对地址理解程度越高
打点精度：
    即坐标点的误差范围，分值范围0-100，分值越大，精度越高
    confidence=100，解析误差绝对精度小于20m
    confidence=50，解析误差绝对精度小于1000m
是否精确查找：
    位置的附加信息，是否精确查找。1为精确查找，即准确打点；0为不精确，即模糊打点
地址类型：
    能精确理解的地址类型，包含：UNKNOWN、国家、省、城市、区县、乡镇、村庄、道路、地产小区、商务大厦、政府机构、交叉路口、商圈、生活服务、休闲娱乐、餐饮、宾馆、购物、金融、教育、医疗 、工业园区 、旅游景点 、汽车服务、火车站、长途汽车站、桥 、停车场/停车区、港口/码头、收费区/收费站、飞机场 、机场 、收费处/收费站 、加油站、绿地、门址
    ''')
    info.pack(side='top',fill='both',expand='yes')

    #输入框绑定变量path
    frm1 = tk.Frame(main_box)
    frm1.pack(side='top',fill='both',expand='yes')
    tk.Label(frm1,text = "边界文件").pack(side='left')
    tk.Entry(frm1, textvariable = path_shp,width=50).pack(side='left')
    tk.Button(frm1, text = "选择文件", command = lambda:selectPath('shp',path_shp)).pack(side='left')

    frm2 = tk.Frame(main_box)
    frm2.pack(side='top',fill='both',expand='yes')
    tk.Label(frm2,text = "地址文件").pack(side='left')
    tk.Entry(frm2, textvariable = path_txt,width=50).pack(side='left')
    tk.Button(frm2, text = "选择文件", command = lambda:selectPath('txt',path_txt)).pack(side='left')

    #边界类型
    # frm3 = tk.Frame(main_box)
    # frm3.pack(side='top',fill='both',expand='yes')
    # tk.Label(frm3,text = "边界类型").pack(side='left')
    # global bjtype
    # bjtype=tk.StringVar()
    # bjtype.set('jp')
    # b1 = tk.Radiobutton(frm3,text='经普',variable=bjtype,value='jp')
    # b1.pack(side='left')
    # b2 = tk.Radiobutton(frm3,text='人普',variable=bjtype,value='rp')
    # b2.pack(side='left')
    #线程调用command=execThread,直接调用command=execProcess
    tk.Button(main_box, text = "执行匹配", command = execThread).pack(side='top',fill='both',expand='yes')
    #输出处理进度
    global outinfo
    outinfo = tk.Text(main_box,height=10)
    outinfo.pack(side='top')
    loginform(main_box)
    main_box.mainloop()

def execThread():
    T = threading.Thread(target=execProcess,args=(gb_apitype,))
    T.start()


def loginform(main_box):
    logindlg = tk.Toplevel()
    logindlg.title('第七次人口普查地址匹配工具')
    logindlg.wm_attributes('-topmost',1)
    def quitapp():
        main_box.quit()
    logindlg.protocol('WM_DELETE_WINDOW', quitapp)
    #输入框绑定变量path
    frm1 = tk.Frame(logindlg)
    frm1.pack(side='top',fill='both',expand='yes')
    tk.Label(frm1,text = "手机号").pack(side='left')
    global mobile
    mobile = tk.Entry(frm1, width=50)
    mobile.pack(side='left')
    frm2 = tk.Frame(logindlg)
    frm2.pack(side='top',fill='both',expand='yes')
    tk.Label(frm2,text = "验证码").pack(side='left')
    tk.Entry(frm2,width=50).pack(side='left')
    tk.Button(frm2, text = "发送验证码", command = sendacccode).pack(side='top',fill='both',expand='yes')

    tk.Button(logindlg, text = "登录", command = lambda:login(main_box,logindlg)).pack(side='top',fill='both',expand='yes')
    logindlg.grab_set()
    logindlg.mainloop()

def login(main_box,logindlg):
    url = "http://124.133.27.90:6082/rp/addressPriv"
    params = {"mobile":mobile.get()}
    global username
    username = params['mobile']
    res = requests.get(url=url,params=params)
    if res.status_code == 200:
        global userjson
        userjson = res.json()
        if 'error' in userjson:
            tkMessageBox.showinfo("错误","验证未通过")
        else:
            # username = mobile.get()
            tkMessageBox.showinfo("信息","验证通过，许可区域为"+userjson['areaname']+",姓名:"+userjson['name'])
            global userareacode
            userareacode = userjson['areacode']
            logindlg.destroy()
            main_box.update()
            main_box.deiconify()
    else:
        tkMessageBox.showinfo("错误","服务器通信异常")

def sendacccode():
    pass
# loginform()
createMainForm()

